package com.hwy.catering.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hwy.catering.dto.UserDto;
import com.hwy.catering.dto.XlsxUserDto;
import com.hwy.catering.entity.User;
import com.hwy.catering.listener.UserXlsxListener;
import com.hwy.catering.mapper.UserMapper;
import com.hwy.catering.service.UserService;
import com.hwy.catering.utils.ConstantPool;
import com.hwy.catering.utils.R;
import com.hwy.catering.utils.UserHolder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.hwy.catering.utils.ConstantPool.*;
import static com.hwy.catering.utils.SystemUtil.mismatch;

/**
* @author 86189
* @description 针对表【tb_user】的数据库操作Service实现
* @createDate 2022-10-29 12:43:14
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private UserXlsxListener userXlsxListener;

    @Resource
    private UserMapper userMapper;

    @Override
    public R detailUser(long id) {
        User user = getById(id);
        System.out.println(user.getId());
        return R.success(user);
    }

    @Override
    public R initRoot(long id) {
        String token = stringRedisTemplate.opsForValue().get(USER_TOKEN_KEY + id);
        Object isRoot = stringRedisTemplate.opsForHash().get(TOKEN_KEY + token, "isRoot");
        Object stop = stringRedisTemplate.opsForHash().get(TOKEN_KEY + token, "stop");
        HashMap<Object, Object> map = new HashMap<>();
        map.put("isRoot",isRoot);
        map.put("stop",stop);
        return R.success(map);
    }

    @Override
    public R deleteUser(long id) {
        userMapper.deleteById(id);
        return R.success("删除用户成功");
    }

    @Override
    public R editUser(User user) {
        boolean b = updateById(user);
        return R.success("更改成功。");
    }

//    @Transactional
    @Override
    public void changeStop(long id, int stop) {
        User user = getById(id);
        user.setStop(stop);
        boolean b = updateById(user);

        String token = stringRedisTemplate.opsForValue().get(USER_TOKEN_KEY + id);
        if (token != null){
            stringRedisTemplate.opsForHash().put(TOKEN_KEY + token,"stop", String.valueOf(stop));
        }
        System.out.println("stop发生变更，变更结果为："+ b+":"+stop);
    }

//    @Transactional
    @Override
    public void changeRoot(long id,int root) {
        User user = getById(id);
        user.setIsRoot(root);
        boolean b = updateById(user);
        String token = stringRedisTemplate.opsForValue().get(USER_TOKEN_KEY + id);
        if (token != null){
            stringRedisTemplate.opsForHash().put(TOKEN_KEY + token,"isRoot", String.valueOf(root));
        }
        System.out.println("root发生变更，变更结果为："+ b+":"+root);
    }

    @Override
    public R importUser(MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(),
                    XlsxUserDto.class,//用什么类接
                    userXlsxListener).sheet().doRead();
            System.out.println("xlsxuser导入成功。");
            return R.success("xlsxUser导入成功。");
        } catch (IOException e) {
            System.out.println("xlsxuser导入失败。");
            return R.error("xlsxUser导入失败。");
        }
    }

    @Override
    public void exportUser(HttpServletResponse response) {
        try {
            //设置下载信息
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码
            String fileName = URLEncoder.encode("课程分类", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");

            //查询所有用户信息
            List<User> users = baseMapper.selectList(null);
            /**
             * easyexcel，默认是支持Date日期格式的导出的，但是不支持LocalDateTime日期格式，所以报错：
             *        com.alibaba.excel.exception.ExcelDataConvertException: Can not find 'Converter' support class LocalDateTime.
             * 解决方法:自定义LocalDateStringConverter
             */
            //EasyExcel写操作
            EasyExcel.write(response.getOutputStream(), User.class)
                    .sheet("用户信息")
                    .doWrite(users);
            System.out.println("user导出xlsx成功");
        }catch(Exception e) {
            System.out.println("user导出xlsx失败.");
        }
    }

    @Override
    public R logout() {
        String token = UserHolder.getUser().getToken();
        Object id = stringRedisTemplate.opsForHash().get(TOKEN_KEY + token, "id");
        stringRedisTemplate.delete(TOKEN_KEY + token);
        stringRedisTemplate.delete(USER_TOKEN_KEY + id);
        return R.success("退出系统。");
    }

    @Override
    public R login(User user) {
        //1.判断账号是否为手机号格式
        boolean isPhone = mismatch(user.getAccount(), ConstantPool.PHONE_REGEX);
        if (isPhone == false){
            return R.error("请输入正确的账号格式。");
        }
        //2.查询该账号是否存在
        Integer exist = query().eq("account", user.getAccount()).count();
        if (exist == 1){
            User user1 = query().eq("account", user.getAccount()).
                    eq("password", user.getPassword()).
                    eq("is_stop", 0).one();
            if (user1 == null){
                return R.error("密码错误或已经被禁用。");
            }
            //3.随机生成token
            String token = UUID.randomUUID().toString();

            //4.token存入redis,过期时间30分钟
            UserDto userDto = BeanUtil.copyProperties(user1, UserDto.class);
            userDto.setToken(token);
            Map<String, Object> userMap = BeanUtil.beanToMap(userDto,new HashMap<>(),
                    //String类型转Long失败的对策
                    CopyOptions.create()
                            /**
                             * 问题：NullPointerException空指针异常
                             * 1.setFieldValueEditor优先级要高于ignoreNullValue导致前者首先被触发，因此出现空指针问题。
                             *   你在setFieldValueEditor中也需要判空。
                             * 2.这么设计的原因主要是，如果原值确实是null，但是你想给一个默认值，在此前过滤掉就不合理了，而
                             *   你的值编辑后转换为null，后置的判断就会过滤掉。
                             */
//                        .setIgnoreNullValue(true)
                            .setFieldValueEditor((fieldName,fieldValue) -> {
                                if (fieldValue == null){
                                    fieldValue = "0";
                                }else {
                                    fieldValue = fieldValue.toString();
                                }
                                return fieldValue;
                            }));

            userMap.put("isRoot", String.valueOf(user1.getIsRoot()));
            userMap.put("stop",String.valueOf(user1.getStop()));
            stringRedisTemplate.opsForValue().set(USER_TOKEN_KEY + user1.getId(),token,USER_TOKEN_KEY_TTL,TimeUnit.MINUTES);
            stringRedisTemplate.opsForHash().putAll(TOKEN_KEY + token,userMap);
            stringRedisTemplate.expire(TOKEN_KEY + token,TOKEN_KEY_TTL, TimeUnit.MINUTES);

            System.out.println(userDto);
            //5.返回token给前端
            return R.success(userDto);
        }
        else {
            return R.error("该账号不存在。");
        }
    }

    @Override
    public R addUser(User user) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("account", user.getAccount());
        //判断改号码是否已经存在
        User one = getOne(wrapper);
        if (one == null){
            save(user);
            return R.success("新用户添加成功");
        }
        return R.error("该号码已经注册过");
    }

    //分页查询用户
    @Override
    public R userPage(Page<User> pageParam, User user) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (user.getId() != null ){
            wrapper.eq("id",user.getId());
        }
        if (user.getName() != null && user.getName() != "") {
            wrapper.eq("name", user.getName());
        }
        if (user.getAccount() != null && user.getAccount() != "") {
            wrapper.eq("account", user.getAccount());
        }
        Page<User> page = page(pageParam, wrapper);
        List<User> records = page.getRecords();
        for (User user1 : records){
            HashMap<String, Object> hashMap = new HashMap<>();
            if (user1.getIsRoot() == 0){
                hashMap.put("isRoot",true);
                user1.setParam(hashMap);
            }else {
                hashMap.put("isRoot",false);
                user1.setParam(hashMap);
            }
            if (user1.getStop() == 0){
                hashMap.put("stop",true);
                user1.setParam(hashMap);
            }else {
                hashMap.put("stop",false);
                user1.setParam(hashMap);
            }
        }
        return R.success(page);
    }
}
